import cv2
import requests
import base64
from concurrent.futures import ThreadPoolExecutor

from detect import CLASSES
from logger import get_logger


# 这个东西的存在是因为报警的种类太多了，全塞一块很乱，所以就弄了个接口（Trigger父类）用于实现各种各样的报警触发方式
# 不用这个类来继承，用下面两个特定时机的触发类
class _AlertTrigger:

    _alert_collect_url = None
    _logger = get_logger('nvrpro.alert')
    _threadpool = ThreadPoolExecutor()

    def __init__(self, alert_objs):
        self.alert_objs = {obj for obj in alert_objs if obj in CLASSES} if alert_objs else set()

    @staticmethod
    def set_alert_collect_url(alert_collect_url):
        _AlertTrigger._alert_collect_url = alert_collect_url
    
    @staticmethod
    def alert_to_cloud(json):
        def wrapper():
            if not _AlertTrigger._alert_collect_url:
                _AlertTrigger._logger.warning(f'没有设置报警收集地址，报警信息将不会推送，报警内容为: {json["target"]}')
                return
            warning_msg = f'推送警报信息失败，推送地址为: {_AlertTrigger._alert_collect_url}，报警内容为: {json["target"]}'
            try:
                r = requests.post(_AlertTrigger._alert_collect_url, json=json)
                if not r.ok or r.json()['code'] != 0:
                    _AlertTrigger._logger.warning(warning_msg)
            except Exception:
                _AlertTrigger._logger.warning(warning_msg)
        _AlertTrigger._threadpool.submit(wrapper)
    
    @staticmethod
    def encode_jpg_image(image):
        return str(base64.b64encode(cv2.imencode('.jpg', image)[1].tobytes()), 'utf-8')
    
    def enter(self, obj, objs):
        pass
    
    def leave(self, obj, objs):
        pass

    def is_obj_enter_trigger(self):
        return False

    def is_obj_leave_trigger(self):
        return False

def set_alert_collect_url(alert_collect_url):
    _AlertTrigger.set_alert_collect_url(alert_collect_url)

# 物体进入时触发
class ObjectEnterTrigger(_AlertTrigger):

    def is_obj_enter_trigger(self):
        return True

# 物体离开时触发
class ObjectLeaveTrigger(_AlertTrigger):

    def is_obj_leave_trigger(self):
        return True

# 物体离开时触发
class ObjectEnterLeaveTrigger(_AlertTrigger):

    def is_obj_enter_trigger(self):
        return True

    def is_obj_leave_trigger(self):
        return True
